﻿using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using YogaDictionary.Common;

namespace YogaDictionary.Model
{
    sealed class DatabaseContext : DbContext
    {
        public DbSet<Glossary> Glossaries { get; set; }
        public DbSet<Definition> Definitions { get; set; }
        public DbSet<Word> Words { get; set; }
        public DbSet<Description> Descriptions { get; set; }
    }

    public class Glossary
    {
        #region Database members

        public long GlossaryId { get; set; }
        public bool Active { get; set; }
        [StringLength(100)]
        public string Name { get; set; }
        [StringLength(100)]
        public string Author { get; set; }
        public string Description { get; set; }

        public virtual ICollection<Definition> Definitions { get; set; }

        #endregion

        #region Other members

        public override string ToString()
        {
            return string.Format("Glossary {0} (ID: {1}) Number of definitions: {2}",
                Name, GlossaryId, Definitions.IsNullOrEmpty() ? 0 : Definitions.Count);
        }

        #endregion
    }

    public class Definition
    {
        #region Database members

        public long DefinitionId { get; set; }
        public bool Active { get; set; }

        public long GlossaryId { get; set; }
        public virtual Glossary Glossary { get; set; }

        public virtual ICollection<Word> Words { get; set; }
        public virtual ICollection<Description> Descriptions { get; set; }

        #endregion

        #region Other members

        [NotMapped]
        public List<Word> PrimaryWords
        {
            get { return Words.IsNullOrEmpty() ? null : Words.Where(w => w.IsPrimary).ToList(); }
        }

        [NotMapped]
        public List<Description> PrimaryDescriptions
        {
            get { return Descriptions.IsNullOrEmpty() ? null : Descriptions.Where(w => w.IsPrimary).ToList(); }
        }

        [NotMapped]
        public List<Word> SecondaryWords
        {
            get { return Words.IsNullOrEmpty() ? null : Words.Where(w => !w.IsPrimary).ToList(); }
        }

        [NotMapped]
        public List<Description> SecondaryDescriptions
        {
            get { return Descriptions.IsNullOrEmpty() ? null : Descriptions.Where(w => !w.IsPrimary).ToList(); }
        }

        public override string ToString()
        {
            return string.Format("Definition ID: {0} Glossary: {1} (ID: {2}) Number of words: {3} Number of descriptions: {4}",
                DefinitionId, Glossary.Name, GlossaryId, Words.IsNullOrEmpty() ? 0 : Words.Count, Descriptions.IsNullOrEmpty() ? 0 : Descriptions.Count);
        }

        #endregion
    }

    public class Word
    {
        #region Database members

        public long WordId { get; set; }
        public bool Active { get; set; }

        [StringLength(100)]
        public string Value { get; set; }
        public bool IsPrimary { get; set; }

        public long DefinitionId { get; set; }
        public virtual Definition Definition { get; set; }

        #endregion

        #region Other members

        public override string ToString()
        {
            var str = string.Format("Word {0} (ID: {1}) Primary: {2} DefinitionId: {3}", Value, WordId, IsPrimary, DefinitionId);
            if (Definition != null && Definition.Words != null)
                str += " Definition words number: " + Definition.Words.Count;
            return str;
        }

        #endregion

    }

    public class Description
    {
        #region Database members

        public long DescriptionId { get; set; }
        public bool Active { get; set; }

        public string Value { get; set; }
        public bool IsPrimary { get; set; }

        public long DefinitionId { get; set; }
        public virtual Definition Definition { get; set; }

        #endregion

        #region Other members

        public override string ToString()
        {
            var str = string.Format("Description {0} (ID: {1}) Primary: {2} DefinitionId: {3}",
                Value, DescriptionId, IsPrimary, DefinitionId);
            if (Definition != null && Definition.Descriptions != null)
                str += " Definition descriptions number: " + Definition.Descriptions.Count;
            return str;
        }

        #endregion

    }
}
